﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Security.Cryptography.Xml;
using System.Text;
using System.Threading.Tasks;
using System.Xml;

namespace LicenseMgr
{
    class SignedHelper
    {
        public static XmlDocument LoadXmlFile(string xmlFile)
        {
            XmlDocument xmlDocument = null;

            xmlDocument = new XmlDocument();
            xmlDocument.Load(xmlFile);
            return xmlDocument;
        }

        public static XmlDocument LoadXml(string xml)
        {
            XmlDocument xmlDocument = null;

            xmlDocument = new XmlDocument();
            xmlDocument.LoadXml(xml);
            return xmlDocument;
        }

        public static string FormatXml(string sUnformattedXml)
        {
            XmlDocument xd = new XmlDocument();
            xd.LoadXml(sUnformattedXml);
            return FormatXml(xd);
        }

        public static string FormatXml(XmlDocument xd)
        {
            StringBuilder sb = new StringBuilder();
            StringWriter sw = new StringWriter(sb);
            XmlTextWriter xtw = null;
            try
            {
                xtw = new XmlTextWriter(sw);
                xtw.Formatting = Formatting.Indented;
                xtw.Indentation = 1;
                xtw.IndentChar = '\t';
                xd.WriteTo(xtw);
            }
            finally
            {
                if (xtw != null)
                    xtw.Close();
            }
            return sb.ToString();
        }

        public static void SignFile(string privateKey, XmlDocument xmldoc, string signedFile)
        {
            // 初始化加密容器
            RSACryptoServiceProvider rSACryptoServiceProvider = new RSACryptoServiceProvider(new CspParameters
            {
                Flags = CspProviderFlags.UseMachineKeyStore
            });
            // 根据私钥加载
            rSACryptoServiceProvider.FromXmlString(privateKey);
            // 配置签名
            SignedXml signedXml = new SignedXml(xmldoc);
            signedXml.SigningKey = rSACryptoServiceProvider;
            Reference reference = new Reference();
            reference.Uri = "";
            XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
            reference.AddTransform(env);
            signedXml.AddReference(reference);
            // 计算签名
            signedXml.ComputeSignature();
            XmlElement xmlDigitalSignature = signedXml.GetXml();
            // 签名附加到文档
            xmldoc.DocumentElement.AppendChild(xmldoc.ImportNode(xmlDigitalSignature, true));
            // 保存签名文件
            xmldoc.Save(signedFile);
        }

        public static bool CheckSignature(string publicKey, string signedFile)
        {
            RSACryptoServiceProvider rSACryptoServiceProvider = new RSACryptoServiceProvider(new CspParameters
            {
                Flags = CspProviderFlags.UseMachineKeyStore
            });
            rSACryptoServiceProvider.FromXmlString(publicKey);
            XmlDocument xmlDocument = null;

            xmlDocument = new XmlDocument();
            xmlDocument.Load(signedFile);
            SignedXml signedXml = new SignedXml(xmlDocument);
            try
            {
                XmlNode xmlNode = xmlDocument.GetElementsByTagName("Signature", "http://www.w3.org/2000/09/xmldsig#")[0];
                signedXml.LoadXml((XmlElement)xmlNode);
            }
            catch (Exception value)
            {
                return false;
            }
            return signedXml.CheckSignature(rSACryptoServiceProvider);
        }
    }
}
